package pers.xdrodger.simple.test.ppt.poi.practice;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFChart;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.junit.Test;
import pers.xdrodger.simple.test.ppt.poi.FileUtil;

import java.awt.geom.Rectangle2D;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

public class CreateBarChart {
    @Test
    public void createBarChart() throws Exception {
        String[] series = new String[] {
                "敬业度指数",
                "全行业均分"
        };
        List<ChartData> dataList = getDataList();

        // Category Axis Data
        List<String> deptList = dataList.stream().map(ChartData::getName).collect(Collectors.toList());
        String[] categories = deptList.toArray(new String[0]);
        // Values
        List<Double> eeiList = dataList.stream().map(ChartData::getValue).collect(Collectors.toList());
        List<Double> normList = dataList.stream().map(ChartData::getValue2).collect(Collectors.toList());
        Double[] values1 = eeiList.toArray(new Double[0]);
        Double[] values2 = normList.toArray(new Double[0]);
        String chartTitle = "部门敬业度";
        XMLSlideShow ppt = new XMLSlideShow();
        XSLFSlide slide = ppt.createSlide();
        XSLFChart chart = ppt.createChart();
        Rectangle2D rect2D = new java.awt.Rectangle(fromCM(1.5), fromCM(4), fromCM(22), fromCM(14));
        slide.addChart(chart, rect2D);

        // Use a category axis for the bottom axis.
        XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        bottomAxis.setTitle("");
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        leftAxis.setTitle(series[0]+","+series[1]);
        leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        leftAxis.setMajorTickMark(AxisTickMark.OUT);
        leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

        final int numOfPoints = categories.length;
        final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
        final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
        final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
        final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
        final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
        valuesData.setFormatCode("0.00%");
//        values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
        final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
//        valuesData2.setFormatCode("General");
        valuesData2.setFormatCode("0.00%");


        XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
        bar.setBarGrouping(BarGrouping.CLUSTERED);
//        bar.setBarGrouping(BarGrouping.PERCENT_STACKED);

        XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
        series1.setTitle(series[0], chart.setSheetTitle(series[COLUMN_COUNTRIES - 1], COLUMN_COUNTRIES));

        XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
        series2.setTitle(series[1], chart.setSheetTitle(series[COLUMN_SPEAKERS - 1], COLUMN_SPEAKERS));

        bar.setVaryColors(true);
        bar.setBarDirection(BarDirection.COL);
        chart.plot(bar);

        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.LEFT);
        legend.setOverlay(false);

        chart.setTitleText(chartTitle);
        chart.setTitleOverlay(false);
        chart.setAutoTitleDeleted(false);

        // save the result
        try (OutputStream out = new FileOutputStream(FileUtil.getOutputFilePath() + "create-bar-chart.pptx")) {
            ppt.write(out);
        }
    }

    private static int fromCM(double cm) {
        return (int) (Math.rint(cm * Units.EMU_PER_CENTIMETER));
    }

    private List<ChartData> getDataList() {
        List<ChartData> result = new ArrayList<>();
//        result.add(new ChartData("管理团队", 83.3, 69.2));
//        result.add(new ChartData("综合事务部", 62.5, 69.2));
//        result.add(new ChartData("工程部", 70.0, 69.2));
//        result.add(new ChartData("生产部", 59.3, 69.2));
        result.add(new ChartData("管理团队", 0.833, 0.692));
        result.add(new ChartData("综合事务部", 0.625, 0.692));
        result.add(new ChartData("工程部", 0.7, 0.692));
        result.add(new ChartData("生产部", 0.593, 0.692));
        return result;
    }

    @AllArgsConstructor
    @Data
    private class ChartData {
        private String name;
        private Double value;
        private Double value2;

    }

    private static final int COLUMN_LANGUAGES = 0;
    private static final int COLUMN_COUNTRIES = 1;
    private static final int COLUMN_SPEAKERS = 2;
}
